home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 006 / stripc / stripc.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  6KB  |  187 lines

  1. /*
  2.  * Article 1436 of net.micro.amiga:
  3.  * Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site well.UUCP
  4.  * Posting-Version: version B 2.10.2 9/5/84; site yale.ARPA
  5.  * Path: well!ptsfa!qantel!lll-crg!ucdavis!ucbvax!decvax!yale!umetcalf
  6.  * From: umetcalf@yale.ARPA (Chris Metcalf)
  7.  * Newsgroups: net.micro.amiga
  8.  * Subject: stripc.c -- strip your include files down to size!
  9.  * Message-ID: <186@yale.ARPA>
  10.  * Date: 4 Jan 86 20:19:26 GMT
  11.  * Date-Received: 5 Jan 86 12:53:49 GMT
  12.  * Reply-To: umetcalf@yale-cheops.UUCP (Chris Metcalf)
  13.  * Distribution: net
  14.  * Organization: Yale University CS Dept., New Haven CT
  15.  * Lines: 165
  16.  */
  17.  
  18. /*
  19.  * This program should be run on all the files in your /include directory.
  20.  * It simple-mindedly strips out comments and much of the extra whitespace.
  21.  * It may fragment the disk a bit, however (by creating and renaming temp 
  22.  * files), so you may want to do a loogical copy of the disk when you're done.
  23.  * The program can be used either with an argument (stripc stdio.h),
  24.  * or as a filter (stripc < stdio.h > test.h).
  25.  * 
  26.  * Enjoy!
  27.  *                 Chris 
  28.  * 
  29.  */
  30.  
  31. /*
  32.  * stripc.c
  33.  * 
  34.  *     This program removes all comments from the selected file (either
  35.  * a command-line argument or standard input).  It also removes much of
  36.  * the excess whitespace while attempting to preserve the basic 
  37.  * arrangement of the program text.
  38.  *
  39.  * Chris Metcalf
  40.  * Jan 2, 1986
  41.  */
  42.  
  43. #include <stdio.h>
  44. #include <ctype.h>
  45.  
  46. #define bool char
  47. #define TRUE 1
  48. #define FALSE 0
  49.  
  50. char nextchar();        /* returns next non-comment character */
  51. void strip_blanks();
  52. #define WS 0x80            /* ORed into whitespace characters */
  53.  
  54. main (argc, argv)
  55. char **argv;
  56. {
  57.   char tmpfile[32];    /* temp name of stripped file */
  58.   char *name;        /* name of this program (stripc) */
  59.   FILE *in, *out;    /* file descriptors for parameter files */
  60.  
  61.   /* read filename arguments -- syntax: stripc [filename filename ...] */
  62.  
  63.   name = argv[0];
  64.   if (argc == 1) strip_blanks(stdin, stdout);
  65.   else while (*++argv) {
  66.     if ((in = fopen(*argv, "r")) == NULL) {
  67.       fprintf(stderr, "%s: couldn't open file %s\n", name, *argv);
  68.       exit(1);
  69.     }
  70.     if ((out = fopen(strcat(strcpy(tmpfile, *argv), ".t"), "w")) == NULL) {
  71.       fprintf(stderr, "%s: couldn't open temp file %s\n", name, tmpfile);
  72.       exit(1);
  73.     }
  74.     strip_blanks(in, out);
  75.     fclose(in);
  76.     fclose(out);
  77.     if (unlink(*argv)) {
  78.       fprintf(stderr, "%s: couldn't remove %s\n", name, *argv);
  79.       exit(1);
  80.     }
  81.     if (rename(tmpfile, *argv)) {
  82.       fprintf(stderr, "%s: couldn't rename %s as %s\n",name,*argv,tmpfile);
  83.       exit(1);
  84.     }
  85.   }
  86. }
  87.  
  88. /*
  89.  * read characters through nextchar(), eliminating white space
  90.  */
  91.  
  92. void strip_blanks(in, out)
  93. FILE *in, *out;
  94. {
  95.   char c;        /* current character */
  96.   char lastws = 0;    /* the white space character being buffered */
  97.   bool ws;        /* set if current character if white space */
  98.  
  99.   while ((c = nextchar(in)) != EOF) {
  100.     ws = c & WS;
  101.     c &= ~WS;
  102.     if (lastws) {
  103.       if (!ws) {
  104.     putc(lastws, out);
  105.     putc(c, out);
  106.     lastws = 0;
  107.       }
  108.       else if (c == '\n' || c == '\r' || c == '\f') lastws = '\n';
  109.       else if (c == '\t' && lastws != '\n') lastws = '\t';
  110.       else if (c == ' ' && lastws != '\n' && lastws != '\t') lastws = ' ';
  111.     }
  112.     else if (ws) lastws = (c=='\r'||c=='\f')?'\n':c;
  113.     else putc(c, out);
  114.   }
  115.   if (lastws) putc(lastws, out);
  116. }
  117.  
  118. char nextchar (in)
  119. FILE *in;
  120. {
  121.   char c;              /* current character being read */
  122.   bool modes;              /* a temp variable for testing all modes */
  123.   static char next;          /* the character waiting to be read */
  124.   static bool init = TRUE,      /* is the first time through the loop */
  125.     comments = FALSE,          /* whether we're in a block of comments */
  126.     oldcomments = FALSE,      /* whether we WERE in a block of comments */
  127.     quotes = FALSE,         /* whether we're in double quotes */
  128.     single = FALSE,         /* in single quotes */
  129.     preproc = FALSE,         /* in a # line (preprocessor command) */
  130.     demagic = FALSE,         /* was the previous character a backslash */
  131.     newline = TRUE;         /* was the previous character a newline */
  132.  
  133.   /* establish lookahead the first time the routine is called */
  134.  
  135.   if (init) {
  136.     next = getc(in);
  137.     init = FALSE;
  138.   }
  139.  
  140.   /*
  141.    * The main do statement loops until a "real" character is found,
  142.    * or the end of file is encountered.  The initial state of preproc,
  143.    * quotes, single, and comments are saved so that transitions from
  144.    * state to state during the "switch" can be eliminated in the output.
  145.    *
  146.    * The switch statement handles the work and the strange cases.
  147.    * If a # is found and the previous character was a newline, and
  148.    * we're not in comments mode, preprocessor mode is set TRUE.  
  149.    * Preprocessor mode is ended by a newline (unless it's escaped).
  150.    * Comments mode is set if a / is followed by a *, and none of
  151.    * the other modes (preproc, quotes, single) are set.  Comments mode
  152.    * is ended by * followed by / unless it's in a preprocessor line.
  153.    * Single quotes mode is toggled on and off by ', unless we're in
  154.    * double quotes or a comment mode, or the ' is escaped.  Double
  155.    * quotes function similarly.  Note that single and double quotes
  156.    * mode can be erroneously set during preprocessor lines, but this
  157.    * is unimportant, since the code for newline already turns off quotes
  158.    * mode at the end of a line (to guard against mismatched quotes).
  159.    */
  160.  
  161.   do {
  162.     if ( (c = next) == EOF) {
  163.       init = TRUE;
  164.       return (EOF);
  165.     }
  166.     next = getc(in);
  167.     modes = preproc || quotes || single;
  168.     oldcomments = comments;
  169.     switch (c) {
  170.       case '#': if (newline && !comments) preproc = TRUE; break;
  171.       case '\n': if (!demagic) preproc = single = quotes = FALSE; break;
  172.       case '/': if (!quotes && !single && next == '*') comments = TRUE; break;
  173.       case '*': if (comments && next == '/') comments = FALSE; break;
  174.       case '\'': if (!comments && !demagic && !quotes) single = !single; break;
  175.       case '"': if (!comments && !demagic && !single) quotes = !quotes; break;
  176.     }
  177.     demagic = ( !demagic && (c == '\\') );
  178.     newline = ( !demagic && (c == '\n') );
  179.     if ( comments != oldcomments )
  180.       next = getc(in);  /* we don't want to have to read it again */
  181.   } while (comments || oldcomments);
  182.   if ((!isprint(c) || c == ' ') && !quotes && !single) c |= WS;
  183.   return c;
  184. }
  185.  
  186.  
  187.